home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 July / macformat-026.iso / mac / Shareware City / Science / µSim 1.0 folder / Libs / StdGetFolder.c < prev    next >
Encoding:
Text File  |  1995-03-10  |  7.3 KB  |  285 lines  |  [TEXT/MMCC]

  1. /*
  2. Copyright © 1993,1994 by Fabrizio Oddone
  3. ••• ••• ••• ••• ••• ••• ••• ••• ••• •••
  4. This source code is distributed as freeware: you can copy, exchange, modify this
  5. code as you wish. You may include this code in any kind of application: freeware,
  6. shareware, or commercial, provided that full credits are given.
  7. You may not sell or distribute this code for profit.
  8. */
  9.  
  10. /* I did not write the code in this file; I took it from some sample code
  11. from Apple, I think.
  12. I modified the original code a little bit, though. */
  13.  
  14. //#pragma load "MacDump"
  15. #include    "UtilsSys7.h"
  16. #include    "StdGetFolder.h"
  17.  
  18. /* typedefs */
  19.  
  20. typedef struct {
  21.     StandardFileReply *replyPtr;
  22.     void (*updateProc)(EventRecord *);
  23.     void (*activateProc)(EventRecord *);
  24.     FSSpec oldSelection;
  25.     short    SelectStrRsrc;
  26. //    short    DeskStrRsrc;
  27. } SFData, *SFDataPtr;
  28.  
  29. /* prototypes */
  30.  
  31. static pascal short MyDlgHook(short item, DialogPtr theDlg, SFDataPtr sfp);
  32. static pascal Boolean MyModalFilter(DialogPtr theDlg, EventRecord *ev, short *itemHit, SFDataPtr myData);
  33. //static pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr);
  34. static void SetSelectButtonName(ConstStr255Param selName, const DialogPtr theDlg, short, Boolean);
  35. static Boolean SameFile(const FSSpecPtr file1, const FSSpecPtr file2);
  36. static OSErr GetDeskFolderSpec(FSSpecPtr, short vRefNum);
  37. static OSErr MakeCanonFSSpec(FSSpecPtr);
  38. static Boolean ShouldHiliteSelect(FSSpecPtr);
  39.  
  40. /* constants */
  41.  
  42. #define    kSelectItem            10
  43. #define    kCanSelectDesktop    true
  44. #define    kSelectKey            's'
  45.  
  46. /* globals */
  47.  
  48. Boolean    gHasFindFolder;
  49. FSSpec    gDeskFolderSpec;
  50.  
  51. /*
  52.     strHndl = GetString(kSelectStrRsrc);
  53.     strHndl = GetString(kDeskStrRsrc);
  54. */
  55.  
  56. /* do getfile */
  57.  
  58. Boolean CustomGet(FSSpec *fSpec,
  59.                 void (*DoUpdate)(EventRecord *),
  60.                 void (*DoActivate)(EventRecord *),
  61.                 short SFDlgID, short SelectStrRsrc/*, short DeskStrRsrc*/)
  62. {
  63. //FileFilterYDUPP    FilterAllFilesUPP = NewFileFilterYDProc(FilterAllFiles);
  64. DlgHookYDUPP    MyDlgHookUPP = NewDlgHookYDProc(MyDlgHook);
  65. ModalFilterYDUPP    MyModalFilterUPP = NewModalFilterYDProc(MyModalFilter);
  66. Point    where = {-1,-1};
  67. OSType    myType = 'ƒldr';
  68. StandardFileReply    sfReply;
  69. SFData    sfUserData;
  70. Boolean    targetIsFolder, wasAliased;
  71.  
  72. /* initialize user data area */
  73.  
  74. sfUserData.replyPtr = &sfReply;
  75. sfUserData.updateProc = DoUpdate;
  76. sfUserData.activateProc = DoActivate;
  77. sfUserData.oldSelection.vRefNum = -9999;    /* init to ridiculous value */
  78. sfUserData.SelectStrRsrc = SelectStrRsrc;
  79. //sfUserData.DeskStrRsrc = DeskStrRsrc;
  80.  
  81. CustomGetFile(nil, 1, &myType, &sfReply, SFDlgID, where, MyDlgHookUPP,
  82.                 MyModalFilterUPP, nil, nil, &sfUserData);
  83.  
  84. if (sfReply.sfGood) {
  85.     if (ResolveAliasFile(&sfReply.sfFile, true, &targetIsFolder, &wasAliased)) {
  86.         sfReply.sfGood = false;
  87.         }
  88.     else if (StrLength(sfReply.sfFile.name) == 0) {
  89.         (void) FSMakeFSSpecCompat(sfReply.sfFile.vRefNum, sfReply.sfFile.parID, nil, fSpec);
  90. //        sfReply.sfGood = false;
  91.         }
  92.     else
  93.         *fSpec = sfReply.sfFile;
  94.     }
  95.  
  96. if (MyModalFilterUPP)
  97.     DisposeRoutineDescriptor(MyModalFilterUPP);
  98. if (MyDlgHookUPP)
  99.     DisposeRoutineDescriptor(MyDlgHookUPP);
  100. //if (FilterAllFilesUPP)
  101. //    DisposeRoutineDescriptor(FilterAllFilesUPP);
  102.  
  103. return sfReply.sfGood;
  104. }
  105.  
  106.  
  107. /*    this dialog hook checks the contents of the additional edit fields
  108.     when the user selects a file.  The focus of the dialog is changed if one
  109.     of the fields is out of range.Ptr userData
  110. */
  111.  
  112. pascal short MyDlgHook(short item, DialogPtr theDlg, SFDataPtr sfUserData)
  113. {
  114. FSSpec curSpec;
  115.  
  116. if (GetWRefCon(theDlg) == sfMainDialogRefCon) {    
  117. //    sfUserData = (SFDataPtr) userData;
  118.     
  119.     if (item != sfHookFirstCall && item != sfHookLastCall) {
  120. /*        if (item == sfItemVolumeUser) {
  121.             sfUserData->replyPtr->sfFile.name[0] = '\0';
  122.             sfUserData->replyPtr->sfFile.parID = fsRtDirID;
  123.             sfUserData->replyPtr->sfIsFolder = false;
  124.             sfUserData->replyPtr->sfIsVolume = false;
  125.             sfUserData->replyPtr->sfFlags = 0;
  126.             item = sfHookChangeSelection;
  127.             }
  128. */
  129.         if (!SameFile(&sfUserData->replyPtr->sfFile, &sfUserData->oldSelection)) {
  130.             curSpec = sfUserData->replyPtr->sfFile;
  131.             (void)MakeCanonFSSpec(&curSpec);
  132.             
  133.             if (curSpec.vRefNum != sfUserData->oldSelection.vRefNum)
  134.                 GetDeskFolderSpec(&gDeskFolderSpec, curSpec.vRefNum);    
  135.             SetSelectButtonName(curSpec.name, theDlg, sfUserData->SelectStrRsrc, ShouldHiliteSelect(&curSpec));
  136.         
  137.             sfUserData->oldSelection = sfUserData->replyPtr->sfFile;
  138.             }
  139.  
  140.         if (item == kSelectItem)
  141.             item = sfItemOpenButton;
  142.         }
  143.     }
  144. return item;
  145. }
  146.  
  147.  
  148. pascal Boolean MyModalFilter(DialogPtr theDlg, EventRecord *ev, short *itemHit, SFDataPtr myData)
  149. {
  150. Boolean evHandled = false;
  151. char keyPressed;
  152.  
  153. if (GetWRefCon(theDlg) == sfMainDialogRefCon)
  154.     switch (ev->what) {
  155.         case keyDown:
  156.         case autoKey:
  157.             keyPressed = CHARFROMMESSAGE(ev->message);
  158.             if (ev->modifiers & cmdKey) {
  159.                 switch (keyPressed) {
  160.                     case kSelectKey:
  161.                         FlashButton(theDlg, kSelectItem);
  162.                         *itemHit = kSelectItem;
  163.                         evHandled = true;
  164.                         break;
  165.                 }
  166.             }
  167.             break;
  168.         case updateEvt:
  169.             if (theDlg != (DialogPtr)ev->message && myData->updateProc) {
  170.                 myData->updateProc(ev);
  171.                 evHandled = true;
  172.                 }
  173.             break;
  174.         case activateEvt:
  175.             if (theDlg != (DialogPtr)ev->message && myData->activateProc) {
  176.                 myData->activateProc(ev);
  177.                 evHandled = true;
  178.                 }
  179.             break;
  180.         }
  181.  
  182. return evHandled;
  183. }
  184.  
  185. /*
  186. pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr)
  187. {
  188. return ((pb->hFileInfo.ioFlAttrib & (1 << 4)) == 0);
  189. }
  190. */
  191.  
  192. void SetSelectButtonName(ConstStr255Param selName, const DialogPtr theDlg, short SelectStrRsrc, Boolean hilited)
  193. {
  194. Str63    storeName, tempLenStr, tempSelName;
  195. Rect    iRect;
  196. StringHandle    theString;
  197. Handle    iHndl;
  198. short    iType;
  199.  
  200. (void) PLstrcpy(tempSelName, selName);
  201. GetDialogItem(theDlg, kSelectItem, &iType, &iHndl, &iRect);
  202.  
  203. /* truncate select name to fit in button */
  204.  
  205. theString = GetString(SelectStrRsrc);
  206.  
  207. (void) PLstrcpy(tempLenStr, *theString);
  208.  
  209. PLstrcat(tempLenStr, "\p “”  ");
  210. TruncString(iRect.right - iRect.left - StringWidth(tempLenStr), tempSelName, smTruncMiddle);
  211.  
  212. (void) PLstrcpy(storeName, *theString);
  213. PLstrcat(storeName, "\p “");
  214. PLstrcat(storeName, tempSelName);
  215. PLstrcat(storeName, "\p”");
  216.  
  217. SetControlTitle((ControlHandle)iHndl, storeName);
  218.  
  219. //SetDItem(theDlg,kSelectItem,iType,iHndl,&iRect);
  220.  
  221. HiliteControl((ControlHandle)iHndl, hilited ? 0 : 255);
  222. ValidRect(&iRect);
  223. }
  224.  
  225.  
  226. Boolean SameFile(const FSSpecPtr file1, const FSSpecPtr file2)
  227. {
  228. return ((file1->vRefNum == file2->vRefNum) &&
  229.         (file1->parID == file2->parID) &&
  230.         (EqualString(file1->name,file2->name,false,true)));
  231. }
  232.  
  233.  
  234. OSErr GetDeskFolderSpec(FSSpecPtr fSpec, short vRefNum)
  235. {
  236. register OSErr err = -1;
  237.  
  238. if (gHasFindFolder) {
  239.     StrLength(fSpec->name) = 0;
  240.     err = FindFolder(vRefNum, kDesktopFolderType, kDontCreateFolder,
  241.                         &fSpec->vRefNum,&fSpec->parID);
  242.     if (err == noErr)
  243.         err = MakeCanonFSSpec(fSpec);
  244.     }
  245. else
  246.     fSpec->vRefNum = -9999;
  247.  
  248. return err;
  249. }
  250.  
  251.  
  252. Boolean ShouldHiliteSelect(FSSpecPtr fSpec)
  253. {
  254. //StringHandle    strHndl;
  255.  
  256. if (CheckVolLock(nil, fSpec->vRefNum))
  257.     return false;
  258. else if (FSpCheckObjectLock(fSpec))
  259.     return false;
  260. else if (SameFile(fSpec, &gDeskFolderSpec)) {
  261. //    strHndl = GetString(DeskStrRsrc);
  262. //    (void) PLstrcpy(fSpec->name, *strHndl);
  263.     return kCanSelectDesktop;
  264.     }
  265. else
  266.     return true;
  267. }
  268.  
  269. OSErr MakeCanonFSSpec(FSSpecPtr fSpec)
  270. {
  271. DirInfo infoPB;
  272. OSErr err = noErr;
  273.  
  274. if (StrLength(fSpec->name) == 0) {
  275.     infoPB.ioNamePtr = fSpec->name;
  276.     infoPB.ioVRefNum = fSpec->vRefNum;
  277.     infoPB.ioDrDirID = fSpec->parID;
  278.     infoPB.ioFDirIndex = -1;
  279.     err = PBGetCatInfoSync((CInfoPBPtr)&infoPB);
  280.     fSpec->parID = infoPB.ioDrParID;
  281.     }
  282. return err;
  283. }
  284.  
  285.